package com.hbx.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbx.dto.menu.UpdateDto;
import com.hbx.exception.RspException;
import com.hbx.mapper.RoleMenuMapper;
import com.hbx.model.Menu;
import com.hbx.mapper.MenuMapper;
import com.hbx.model.RoleMenu;
import com.hbx.service.MenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbx.utils.Result;
import com.hbx.utils.SubMenuUtils;
import com.hbx.vo.PageBean;
import com.hbx.vo.login.MenuVo;
import com.hbx.vo.menu.MenuItemVo;
import com.hbx.vo.menu.TreeMenuVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hbx
 * @since 2021-11-26
 */
@Service
@Slf4j
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    /**
     * 根据用户id获得用户菜单
     * @param userId
     * @return
     */
    @Override
    public Result<MenuVo> getMenuByUserId(Integer userId) {
        Result<MenuVo> r = new Result<>();
        MenuVo menuVo = new MenuVo();
        List<MenuVo.SubMenu> list = new ArrayList<>();
        Map<Integer,MenuVo.SubMenu> map = new HashMap();
        // 获得所有菜单列表
        List<Menu> menuList = menuMapper.selectMenuByUserId(userId);
        // 获得集合迭代器对象
        ListIterator<Menu> iterator = menuList.listIterator();
        while (iterator.hasNext()){
            Menu menuItem = iterator.next();
            // 筛选出父级菜单，一级
            if(menuItem.getParentId() != null && menuItem.getParentId() == 1){
                // 处理展开菜单,有多个默认最后一个
                if(menuItem.getSpread() != null && menuItem.getSpread() == 1){
                    menuVo.getSpread().add(menuItem.getId());
                }
                // 存入待返回集合中
                MenuVo.SubMenu subMenu = SubMenuUtils.menuTransformationSubMenu(menuItem);
                map.put(subMenu.getId(),subMenu);
                // 删掉当前一级菜单
                iterator.remove();
            }
        }
        log.info("【菜单模块】:一级菜单加载完毕,共有{}个一级菜单",map.size());
        Integer count = 0;
        // 为一级菜单追加子菜单
        for (Menu menu : menuList) {
            MenuVo.SubMenu parent = map.get(menu.getParentId());
            if(!ObjectUtils.isEmpty(parent)){
                MenuVo.SubMenu subMenu = SubMenuUtils.menuTransformationSubMenu(menu);
                parent.getChildren().add(subMenu);
                // 处理默认选中
                if(count == 0 && menu.getSpread() != null && menu.getSpread() == 1){
                    menuVo.getSelected().add(menu.getHref());
                    count++;
                }
            }
        }

        //处理map
        for (Map.Entry<Integer, MenuVo.SubMenu> entry:map.entrySet()){
            list.add(entry.getValue());
        }
        menuVo.setMenuList(list);

        return r.setData(menuVo).setCode(200).setMsg("请求成功");
    }

    /**
     * 获得所有菜单
     * @return
     */
    @Override
    public Result getMenuList(Integer pageNum,Integer pageSize) {
        PageBean<List<MenuItemVo>> result = new PageBean<>();
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        Page page = new Page(pageNum,pageSize);
        wrapper.orderByAsc("parent_id");
        IPage iPage = menuMapper.selectPage(page, wrapper);
        List<MenuItemVo> voList = new ArrayList<>();
        iPage.getRecords().stream().forEach(menu -> {
            MenuItemVo vo = new MenuItemVo();
            BeanUtils.copyProperties(menu,vo);
            voList.add(vo);
        });
        log.info("【菜单模块】:获取所有菜单,共{}条",voList.size());
        result.setPageNum(iPage.getCurrent());
        result.setPageSize(iPage.getSize());
        result.setData(voList);
        result.setTotal(iPage.getTotal());
        return Result.ok().setData(result);
    }

    /**
     * 获取所有父菜单id
     * @return
     */
    @Override
    public Result getMenuParentIdList() {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.in("target",new String[]{"1","2"});
        List<Menu> menuList = menuMapper.selectList(wrapper);
        return Result.ok().setData(menuList);
    }

    /**
     * 修改添加菜单
     * @param updateDto
     * @param r
     */
    @Override
    @Transactional
    public void insetUpdateMenuHandler(UpdateDto updateDto, Result r) {
        String target = updateDto.getTarget();
        String href = updateDto.getHref();
        if (updateDto.getId() != null){
            Menu menu = new Menu();
            BeanUtils.copyProperties(updateDto,menu);
            int result = menuMapper.updateById(menu);
            if (result == 1){
                r.setCode(200).setMsg("菜单更新成功");
                log.info("【菜单模块】:菜单更新成功");
            } else {
                r.setCode(201).setMsg("菜单更新失败");
                log.error("【菜单模块】:菜单更新失败");
            }
        } else {
            if ("3".equals(target)){
                if (StringUtils.isEmpty(href)){
                    r.setCode(201).setMsg("菜单路由地址不可为空");
                    return;
                }
                // 校验唯一性
                QueryWrapper<Menu> wrapper = new QueryWrapper<>();
                wrapper.eq("href",href);
                List<Menu> menuList = menuMapper.selectList(wrapper);
                if (!CollectionUtils.isEmpty(menuList)){
                    r.setCode(201).setMsg("添加失败,菜单地址重复");
                    return;
                }
            } else if ("2".equals(target)){
                updateDto.setHref(null);
            }
            Menu menu = new Menu();
            BeanUtils.copyProperties(updateDto,menu);
            int result = menuMapper.insert(menu);
            if (result == 1){
                // 给超管添加菜单
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setRid(1);
                roleMenu.setMid(menu.getId());
                int insert = roleMenuMapper.insert(roleMenu);
                if (insert > 0){
                    r.setCode(200).setMsg("菜单添加成功");
                    log.info("【菜单模块】:菜单添加成功");
                } else {
                    throw new RspException("菜单添加失败");
                }
            } else {
                r.setCode(201).setMsg("菜单添加失败");
                log.error("【菜单模块】:菜单添加失败");
            }
        }
    }

    /**
     * 删除菜单
     * @param id
     */
    @Override
    public void removeMenu(Integer id, Result r) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",id);
        List<Menu> menuList = menuMapper.selectList(wrapper);
        log.info("【菜单模块】:查询子菜单,共有{}条",menuList.size());
        List<Integer> ids = new ArrayList<>();
        if (!CollectionUtils.isEmpty(menuList)){
            ids = menuList.stream()
                    .map(Menu::getId)
                    .collect(Collectors.toList());
        }
        ids.add(id);

        // 删除菜单
        Integer result = menuMapper.deleteBatchIds(ids);
        if (result != null && result > 0){
            r.setCode(200).setMsg("菜单删除成功");
            log.info("【菜单模块】:菜单删除成功,共{}条",result);
        }else {
            r.setCode(201).setMsg("菜单删除失败");
            log.info("【菜单模块】:菜单删除失败");
        }
    }

    /**
     * 获得菜单树形结构
     * @param r
     */
    @Override
    public void getMenuTreeList(Result r) {
        TreeMenuVo treeMenuVo = new TreeMenuVo();
        List<TreeMenuVo> list = new ArrayList<>();
        Map<String,TreeMenuVo> map = new HashMap();
        // 获得所有菜单列表
        List<Menu> menuList = menuMapper.selectList(null);
        // 获得集合迭代器对象
        ListIterator<Menu> iterator = menuList.listIterator();
        while (iterator.hasNext()){
            Menu menuItem = iterator.next();
            if(menuItem.getParentId() != null && menuItem.getParentId() == 0){
                // 存入待返回集合中
                treeMenuVo = SubMenuUtils.menuTransformationTreeMenuVo(menuItem);
                // 删掉当前一级菜单
                iterator.remove();
            }
            // 筛选出父级菜单，一级
            if(menuItem.getParentId() != null && menuItem.getParentId() == 1){
                // 存入待返回集合中
                TreeMenuVo subMenuVo = SubMenuUtils.menuTransformationTreeMenuVo(menuItem);
                map.put(subMenuVo.getKey(),subMenuVo);
                // 删掉当前一级菜单
                iterator.remove();
            }
        }
        log.info("【菜单模块】:一级菜单加载完毕,共有{}个一级菜单",map.size());

        // 为一级菜单追加子菜单
        for (Menu menu : menuList) {
            TreeMenuVo parent = map.get(menu.getParentId() + "");
            if(!ObjectUtils.isEmpty(parent)){
                TreeMenuVo subMenu = SubMenuUtils.menuTransformationSubMenuVo(menu);
                parent.getChildren().add(subMenu);
            }
        }

        //处理map
        for (Map.Entry<String, TreeMenuVo> entry:map.entrySet()){
            list.add(entry.getValue());
        }

        treeMenuVo.setChildren(list);

        r.setCode(200).setData(treeMenuVo).setMsg("请求成功");
    }

    /**
     * 根据用户id查菜单
     * @param userId
     * @return
     */
    @Override
    public List<String> getMenuAuthByUserId(Integer userId) {
        List<Menu> menuList = menuMapper.selectMenuRouteByUserId(userId);
        return menuList.stream().map(Menu::getHref).collect(Collectors.toList());
    }
}
